home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library / Microsoft Programmer's Library (CD-ROM Database)(125-099-008)(Version 1.1a)(CDRM 162100)(1989).iso / SAMPCODE / OS2SDK11 / TK4 / SNAP / SNAP.C < prev    next >
C/C++ Source or Header  |  1989-02-20  |  22KB  |  781 lines

  1. /*
  2.     snap.c -- PM snapshot utility
  3.     Created by Microsoft Corporation, 1989
  4. */
  5. #define        INCL_WIN
  6. #define        INCL_GPI
  7. #define        INCL_DEV
  8. #include    <os2.h>
  9. #include    "snap.h"
  10.  
  11. /* Global variables */
  12. char szSnap[5];
  13.  
  14. HAB    habSnap;
  15. HMQ    hmqSnap;
  16. HWND   hwndSnap, hwndSnapFrame;
  17. HWND   hwndNextClipViewer;
  18. HPS    hpsScr;
  19. HHEAP  hHeap;
  20.  
  21. HPOINTER hptrSnap;
  22. HPOINTER hptrHand;
  23. HPOINTER hptrSelect;
  24.  
  25. RECTL wrcRgn;                   /* holds coordinates of selected region. */
  26. RECTL rcScreen;                 /* rectangle for the screen for bounding */
  27.  
  28. int AboutCount = 0;
  29.  
  30. int  wSnapMode = IDM_WINDOW;    /* snap either selected window or region. */
  31.  
  32. BOOL fSnapWnd = FALSE;  /* snap selected window? */
  33. BOOL fSnapRgn = FALSE;  /* snap selected region? */
  34. BOOL fSelect = FALSE;   /* in the process of selecting region? */
  35. BOOL fNCArea = FALSE;   /* exclude nonclient area of window in snap? */
  36. BOOL fHide = TRUE;      /* hide snap's window while snapping */
  37.  
  38.  
  39. /* Function prototypes */
  40. MRESULT CALLBACK SnapWndProc(HWND, USHORT, MPARAM, MPARAM);
  41. MRESULT CALLBACK AboutWndProc(HWND, USHORT, MPARAM, MPARAM);
  42. MRESULT CALLBACK SaveFileDlgProc(HWND, USHORT, MPARAM, MPARAM);
  43. HFILE OpenSaveFile(HWND);
  44. void SnapWindow(ULONG);
  45. BOOL SnapInit(void);
  46. void SnapPaint(HPS);
  47. void SnapRegion(HPS);
  48. void DrawRgn(HPS);
  49. void SortRect(PRECTL, PRECTL);
  50. void SaveBitmap(void);
  51. void SaveBitmap2(HFILE hFile, HBITMAP hbm);
  52. void convert(NPBYTE pbuf, USHORT cch, USHORT cch2);
  53. HDC CreateDC(PSZ, HDC);
  54. void Copy(NPBYTE, NPBYTE, USHORT);
  55. int cdecl main(void);
  56.  
  57.  
  58. /* Routines */
  59. int cdecl main(void)
  60. {
  61.     QMSG msg;
  62.     ULONG ctlData;
  63.  
  64.     if (!SnapInit())
  65.         return(FALSE);
  66.  
  67.     ctlData = FCF_TITLEBAR | FCF_MINMAX | FCF_SIZEBORDER |
  68.             FCF_SYSMENU | FCF_MENU | FCF_ICON;
  69.     hwndSnapFrame = WinCreateStdWindow(HWND_DESKTOP,
  70.             FS_ICON, &ctlData,
  71.             (PCH)szSnap, (PCH)szSnap,
  72.             0L,
  73.             NULL, 1,
  74.             (HWND far *)&hwndSnap);
  75.  
  76.  
  77.     if (!hwndSnap)
  78.         return(FALSE);
  79.  
  80.     WinSetWindowPos(hwndSnapFrame, 0, 0, 0, 200, 75, SWP_SIZE | SWP_MOVE);
  81.     WinShowWindow(hwndSnapFrame, TRUE);
  82.  
  83.     WinSetFocus(HWND_DESKTOP, hwndSnap);
  84.     WinQueryWindowRect(HWND_DESKTOP, &rcScreen);
  85.  
  86.     if (WinOpenClipbrd(habSnap)) {
  87.         WinSetClipbrdViewer(habSnap, hwndSnap);
  88.         WinCloseClipbrd(habSnap);
  89.     }
  90.  
  91.     while (WinGetMsg(habSnap, (PQMSG)&msg, NULL, NULL, NULL)) {
  92.         WinDispatchMsg(habSnap, (PQMSG)&msg);
  93.     }
  94.  
  95.     WinDestroyPointer(hptrSnap);
  96.     WinDestroyPointer(hptrHand);
  97.     WinDestroyPointer(hptrSelect);
  98.  
  99.     WinDestroyWindow(hwndSnapFrame);
  100.     WinDestroyHeap(hHeap);
  101.     WinDestroyMsgQueue(hmqSnap);
  102.  
  103.     WinTerminate(habSnap);
  104.  
  105.     return 0;
  106. } /* end winmain */
  107.  
  108.  
  109. HDC CreateDC(lpszDriver, hdcCompat)
  110. PSZ lpszDriver;
  111. HDC hdcCompat;
  112. {
  113.     struct {
  114.         ULONG FAR *lpLogAddr;
  115.         PSZ lpszDriver;
  116.     } opendc;
  117.  
  118.     opendc.lpLogAddr = NULL;
  119.     opendc.lpszDriver = lpszDriver;
  120.  
  121.     return((HDC)DevOpenDC(habSnap, OD_MEMORY, (PSZ)"*", 2L,
  122.             (PDEVOPENDATA)&opendc, hdcCompat));
  123. }
  124.  
  125. BOOL SnapInit(void)
  126. {
  127.     /*
  128.      * Initialize the HAB
  129.      */
  130.     habSnap = WinInitialize(NULL);
  131.  
  132.     hmqSnap = WinCreateMsgQueue(NULL, 0);
  133.  
  134.     WinLoadString(habSnap, (ULONG)0, IDS_SNAP, sizeof(szSnap), (PCH)szSnap);
  135.  
  136.     hptrSnap = WinLoadPointer(HWND_DESKTOP, (HMODULE)NULL, IDR_PTR_SNAP);
  137.     hptrHand = WinLoadPointer(HWND_DESKTOP, (HMODULE)NULL, IDR_PTR_HAND);
  138.     hptrSelect = WinLoadPointer(HWND_DESKTOP, (HMODULE)NULL, IDR_PTR_SELECT);
  139.  
  140.     if (!WinRegisterClass(habSnap, (PCH)szSnap, SnapWndProc, (ULONG)0, 0))
  141.         return(FALSE);
  142.  
  143.     if ((hHeap = WinCreateHeap(0, 0, 0, 0, 0, 0)) == NULL)
  144.         return(FALSE);
  145.     /*
  146.      * We assume an empty clipboard when we start.
  147.      */
  148.     WinOpenClipbrd(habSnap);
  149.     WinEmptyClipbrd(habSnap);
  150.     WinCloseClipbrd(habSnap);
  151. } /* end snapinit */
  152.  
  153.  
  154. MRESULT CALLBACK SnapWndProc(hwnd, message, mp1, mp2)
  155. HWND    hwnd;
  156. USHORT  message;
  157. MPARAM  mp1;
  158. MPARAM  mp2;
  159. {
  160.     HWND hwndMenu;
  161.     HPS hps;
  162.     RECTL wrcUpdate;
  163.     POINTL wptTemp;
  164.  
  165.     switch (message) {
  166.         case WM_BUTTON1DOWN:
  167.             if (fSnapWnd) {
  168.                 WinSetPointer(HWND_DESKTOP, hptrSnap);
  169.                 SnapWindow(LONGFROMMP(mp1));
  170.                 WinSetCapture(HWND_DESKTOP, (HWND)NULL);
  171.                 fSnapWnd = FALSE;
  172.             } else if (fSnapRgn) {
  173.                 wptTemp.x = SHORT1FROMMP(mp1);
  174.                 wptTemp.y = SHORT2FROMMP(mp1);
  175.                 WinMapWindowPoints(hwndSnap, (HWND)HWND_DESKTOP,
  176.                         (PPOINTL)&wptTemp, 1);
  177.                 wrcRgn.yTop = wrcRgn.yBottom = wptTemp.y;
  178.                 wrcRgn.xRight = wrcRgn.xLeft = wptTemp.x;
  179.                 hpsScr = WinGetScreenPS(HWND_DESKTOP);
  180.                 DrawRgn(hpsScr);
  181.                 WinReleasePS(hpsScr);
  182.                 fSelect = TRUE;
  183.                 break;
  184.             } else {
  185.                 return(WinDefWindowProc(hwnd, message, mp1, mp2));
  186.             }
  187.             break;
  188.  
  189.         case WM_MOUSEMOVE:
  190.             if (fSelect) {
  191.                 hpsScr = WinGetScreenPS(HWND_DESKTOP);
  192.                 DrawRgn(hpsScr);
  193.                 wptTemp.x = LOUSHORT(mp1);
  194.                 wptTemp.y = HIUSHORT(mp1);
  195.                 WinMapWindowPoints(hwndSnap, (HWND)HWND_DESKTOP,
  196.                         (PPOINTL)&wptTemp, 1);
  197.                 wrcRgn.yTop = wptTemp.y;
  198.                 wrcRgn.xRight = wptTemp.x;
  199.                 DrawRgn(hpsScr);
  200.                 WinReleasePS(hpsScr);
  201.                 break;
  202.             }
  203.             if (fSnapWnd || fSnapRgn) {
  204.                 break;
  205.             } else {
  206.                 return(WinDefWindowProc(hwnd, message, mp1, mp2));
  207.             }
  208.             break;
  209.  
  210.         case WM_BUTTON1UP:
  211.             if (fSelect) {
  212.                 WinSetCapture(HWND_DESKTOP, (HWND)NULL);
  213.                 hpsScr = WinGetScreenPS(HWND_DESKTOP);
  214.                 DrawRgn(hpsScr);
  215.                 SnapRegion(hpsScr);
  216.                 WinReleasePS(hpsScr);
  217.                 fSnapRgn = FALSE;
  218.                 fSelect = FALSE;
  219.             }
  220.             break;
  221.  
  222.         case WM_DRAWCLIPBOARD:
  223.             WinInvalidateRect(hwnd, (PRECTL)NULL, TRUE);
  224.             break;
  225.  
  226.         case WM_PAINT:
  227.             hps = WinBeginPaint(hwnd, NULL, &wrcUpdate);
  228.             WinFillRect(hps, &wrcUpdate, SYSCLR_WINDOW);
  229.             SnapPaint(hps);
  230.             WinEndPaint(hps);
  231.             break;
  232.  
  233.         case WM_INITMENU:
  234.             hwndMenu = WinWindowFromID(hwndSnapFrame, FID_MENU);
  235.             WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(IDM_REGION, TRUE),
  236.                 MPFROM2SHORT(MIA_CHECKED, wSnapMode == IDM_REGION ? MIA_CHECKED : 0));
  237.             WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(IDM_WINDOW, TRUE),
  238.                 MPFROM2SHORT(MIA_CHECKED, wSnapMode == IDM_WINDOW ? MIA_CHECKED : 0));
  239.             WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(IDM_NCAREA, TRUE),
  240.                 MPFROM2SHORT(MIA_CHECKED, fNCArea ? MIA_CHECKED : 0));
  241.             WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(IDM_HIDE, TRUE),
  242.                 MPFROM2SHORT(MIA_CHECKED, fHide ? MIA_CHECKED : 0));
  243.             WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(IDM_NCAREA, TRUE),
  244.                 MPFROM2SHORT(MIA_DISABLED, wSnapMode == IDM_WINDOW ? 0 : MIA_DISABLED));
  245.             break;
  246.  
  247.         case WM_COMMAND:
  248.             switch ((USHORT)mp1) {
  249.                 case IDM_SAVE:
  250.                     SaveBitmap();
  251.                     break;
  252.  
  253.                 case IDM_SNAP:
  254.                     WinSetCapture(HWND_DESKTOP, hwnd);
  255.                     if (fHide)
  256.                         WinShowWindow(hwndSnapFrame, FALSE);
  257.                     if (wSnapMode == IDM_WINDOW) {
  258.                         fSnapWnd = TRUE;
  259.                         WinSetPointer(HWND_DESKTOP, hptrHand);
  260.                     } else {
  261.                         fSnapRgn = TRUE;
  262.                         WinSetPointer(HWND_DESKTOP, hptrSelect);
  263.                     }
  264.                     break;
  265.  
  266.                 case IDM_WINDOW:
  267.                 case IDM_REGION:
  268.                     wSnapMode = SHORT1FROMMP(mp1);
  269.                     break;
  270.  
  271.                 case IDM_NCAREA:
  272.                     fNCArea = !fNCArea;
  273.                     break;
  274.  
  275.                 case IDM_HIDE:
  276.                     fHide = !fHide;
  277.                     break;
  278.  
  279.                 case IDM_ABOUT:
  280.                     WinDlgBox(HWND_DESKTOP, hwnd,
  281.             (PFNWP)AboutWndProc, NULL, IDD_INFO, (PCH)NULL);
  282.                     break;
  283.             }
  284.             break;
  285.  
  286.         default:
  287.             return(WinDefWindowProc(hwnd, message, mp1, mp2));
  288.     }
  289.  
  290.     return(0L);
  291.  
  292. } /* end snapwndproc */
  293.  
  294.  
  295. void SnapPaint(hps)
  296. HPS hps;
  297. {
  298.     HBITMAP hbm;
  299.     POINTL   pt;
  300.     BITMAPINFOHEADER bminfo;
  301.     RECTL rc;
  302.  
  303.     WinOpenClipbrd(habSnap);
  304.     WinQueryWindowRect(hwndSnap, &rc);
  305.  
  306.     if (hbm = WinQueryClipbrdData(habSnap, CF_BITMAP)) {
  307.         GpiQueryBitmapParameters(hbm, &bminfo);
  308.         pt.x = 0;
  309.         pt.y = rc.yTop - bminfo.cy;
  310.         WinDrawBitmap(hps, hbm, (PRECTL)NULL, (PPOINTL)&pt,
  311.                 0L, 0L, DBM_NORMAL | DBM_IMAGEATTRS);
  312.     }
  313.  
  314.     WinCloseClipbrd(habSnap);
  315.  
  316. } /* end SnapPaint */
  317.  
  318.  
  319. void SnapWindow(loc)
  320. ULONG loc;
  321. {
  322.     BITMAPINFOHEADER bminfo;
  323.     POINTL  pt;
  324.     HWND hwnd;
  325.     HWND hwndT;
  326.     RECTL rc, rcTmp;
  327.     HPS  hpsWnd, hpsMem;
  328.     HDC  hdc;
  329.     HBITMAP hbm, hbmOld;
  330.     int  cx, cy;
  331.     POINTL rgpt[3];
  332.     SIZEL size;
  333.  
  334.     pt.y = HIUSHORT(loc);
  335.     pt.x = LOUSHORT(loc);
  336.  
  337.     WinMapWindowPoints(hwndSnap, HWND_DESKTOP, (PPOINTL)&pt, 1);
  338.     if ((hwnd = WinWindowFromPoint(HWND_DESKTOP, (PPOINTL)&pt, FALSE, FALSE)) == NULL)
  339.         return;
  340.     /* get size of target window. clip to screen. */
  341.     if (fNCArea)  /* snap only the client area if it exists */
  342.         if ((hwndT = WinWindowFromID(hwnd, FID_CLIENT)) != NULL)
  343.             hwnd = hwndT;
  344.     WinQueryWindowRect(hwnd, &rcTmp);
  345.     /* bound window rectangle to screen. */
  346.     WinMapWindowPoints(hwnd, HWND_DESKTOP, (PPOINTL)&rcTmp.xLeft, 2);
  347.     WinIntersectRect(habSnap, &rc, &rcTmp, &rcScreen);
  348.     WinMapWindowPoints(HWND_DESKTOP, hwnd, (PPOINTL)&rc.xLeft, 2);
  349.     cx = (USHORT)(rc.xRight - rc.xLeft);
  350.     cy = (USHORT)(rc.yTop - rc.yBottom);
  351.  
  352.     /* get window PS */
  353.     hpsWnd = WinGetPS(hwnd);
  354.  
  355.     /* Create a memory DC */
  356.     hdc = CreateDC((PSZ)"MEMORY", (HDC)NULL);
  357.  
  358.     /* create a memory PS */
  359.     size.cx = cx;
  360.     size.cy = cy;
  361.     hpsMem = GpiCreatePS( habSnap, hdc, &size,
  362.             PU_ARBITRARY | GPIT_NORMAL | GPIA_ASSOC );
  363.  
  364.     /* Create a bitmap */
  365.     bminfo.cbFix = 12;
  366.     bminfo.cx = cx;
  367.     bminfo.cy = cy;
  368.     bminfo.cPlanes = 1;
  369.     bminfo.cBitCount = 4;
  370.     if (!(hbm = GpiCreateBitmap(hpsMem, (PBITMAPINFOHEADER)&bminfo, 0L, 0, 0)))
  371.         WinMessageBox((HWND)HWND_DESKTOP, hwndSnap,
  372.             (PCH)"Insufficient memory to create the bitmap.", (PCH)NULL,
  373.             0, MB_OK);
  374.     else {
  375.         /* put the bitmap into the memory PS */
  376.         hbmOld = GpiSetBitmap(hpsMem, hbm);
  377.  
  378.         /* copy the window to the memory PS */
  379.         rgpt[0].x = 0;
  380.         rgpt[0].y = 0;
  381.         rgpt[1].x = cx;
  382.         rgpt[1].y = cy;
  383.         rgpt[2].x = rc.xLeft;
  384.         rgpt[2].y = rc.yBottom;
  385.         GpiBitBlt(hpsMem, hpsWnd, 3L, (PPOINTL)&rgpt[0], ROP_SRCCOPY, 0L);
  386.  
  387.         /* free the bitmap */
  388.         GpiSetBitmap(hpsMem, hbmOld);
  389.  
  390.         /* store the bitmap */
  391.         WinOpenClipbrd(habSnap);
  392.         WinEmptyClipbrd(habSnap);
  393.         WinSetClipbrdData(habSnap, (ULONG)hbm, CF_BITMAP, CFI_HANDLE);
  394.         WinCloseClipbrd(habSnap);
  395.     }
  396.  
  397.     /* destroy the memory DC */
  398.     GpiAssociate( hpsMem, NULL );
  399.     DevCloseDC(hdc);
  400.  
  401.     /* get rid of the PSs */
  402.     GpiDestroyPS(hpsMem);
  403.     WinReleasePS(hpsWnd);
  404.  
  405.     if (fHide)
  406.         WinShowWindow(hwndSnapFrame, TRUE);
  407.  
  408. } /* end snapwindow */
  409.  
  410.  
  411. void SnapRegion(hpsScr)
  412. HPS hpsScr;
  413. {
  414.     HDC hdc;
  415.     HBITMAP hbm, hbmOld;
  416.     BITMAPINFOHEADER bminfo;
  417.     RECTL rcTmp;
  418.     int cx, cy;
  419.     POINTL rgpt[3];
  420.     HPS hpsMem;
  421.     SIZEL size;
  422.  
  423.     SortRect((PRECTL)&wrcRgn, (PRECTL)&rcTmp);
  424.  
  425.     cx = (USHORT)(rcTmp.xRight - rcTmp.xLeft);
  426.     cy = (USHORT)(rcTmp.yTop - rcTmp.yBottom);
  427.  
  428.     /* Create a memory DC */
  429.     hdc = CreateDC((PSZ)"MEMORY", (HDC)NULL);
  430.  
  431.     /* create a memory PS */
  432.     size.cx = cx;
  433.     size.cy = cy;
  434.     hpsMem = GpiCreatePS( habSnap, hdc, &size,
  435.             PU_ARBITRARY | GPIT_NORMAL | GPIA_ASSOC );
  436.  
  437.     /* Create a bitmap */
  438.     bminfo.cbFix = 12;
  439.     bminfo.cx = cx;
  440.     bminfo.cy = cy;
  441.     bminfo.cPlanes = 1;
  442.     bminfo.cBitCount = 4;
  443.     if (!(hbm = GpiCreateBitmap(hpsMem, (PBITMAPINFOHEADER)&bminfo, 0L, 0, 0))) {
  444.         WinMessageBox((HWND)HWND_DESKTOP, hwndSnap,
  445.             (PCH)"Insufficient memory to create the bitmap.", (PCH)NULL,
  446.             0, MB_OK);
  447.     } else {
  448.         /* put the bitmap into the memory PS */
  449.         hbmOld = GpiSetBitmap(hpsMem, hbm);
  450.  
  451.         /* copy the window to the memory PS */
  452.         rgpt[0].x = 0;
  453.         rgpt[0].y = 0;
  454.         rgpt[1].x = cx;
  455.         rgpt[1].y = cy;
  456.         rgpt[2].x = rcTmp.xLeft;
  457.         rgpt[2].y = rcTmp.yBottom;
  458.         GpiBitBlt(hpsMem, hpsScr, 3L, (PPOINTL)&rgpt[0], ROP_SRCCOPY, 0L);
  459.  
  460.         /* free the bitmap */
  461.         GpiSetBitmap(hpsMem, hbmOld);
  462.  
  463.         /* store the bitmap */
  464.         WinOpenClipbrd(habSnap);
  465.         WinEmptyClipbrd(habSnap);
  466.         WinSetClipbrdData(habSnap, (ULONG)hbm, CF_BITMAP, CFI_HANDLE);
  467.         WinCloseClipbrd(habSnap);
  468.     }
  469.     /* destroy the memory DC */
  470.     GpiAssociate( hpsMem, NULL );
  471.     DevCloseDC(hdc);
  472.  
  473.     /* get rid of the PS */
  474.     GpiDestroyPS(hpsMem);
  475.  
  476.     if (fHide)
  477.         WinShowWindow(hwndSnapFrame, TRUE);
  478.  
  479. } /* end snapregion */
  480.  
  481. void DrawRgn(hps)
  482. HPS hps;
  483. {
  484.     RECTL rc;
  485.  
  486.     SortRect((PRECTL)&wrcRgn, (PRECTL)&rc);
  487.  
  488.     WinDrawBorder(hps, (PRECTL)&rc, 1, 1, SYSCLR_WINDOW, SYSCLR_WINDOW,
  489.             DB_DESTINVERT | DB_STANDARD);
  490. }
  491.  
  492. void SortRect(pwrcIn, pwrcSorted)
  493. PRECTL pwrcIn, pwrcSorted;
  494. {
  495.     if (pwrcIn->yTop > pwrcIn->yBottom) {
  496.         pwrcSorted->yTop = pwrcIn->yTop;
  497.         pwrcSorted->yBottom = pwrcIn->yBottom;
  498.     } else {
  499.         pwrcSorted->yTop = pwrcIn->yBottom;
  500.         pwrcSorted->yBottom = pwrcIn->yTop;
  501.     }
  502.     if (pwrcIn->xRight > pwrcIn-> xLeft) {
  503.         pwrcSorted->xRight = pwrcIn->xRight;
  504.         pwrcSorted->xLeft = pwrcIn->xLeft;
  505.     } else {
  506.         pwrcSorted->xRight = pwrcIn->xLeft;
  507.         pwrcSorted->xLeft = pwrcIn->xRight;
  508.     }
  509. }
  510.  
  511. MRESULT CALLBACK AboutWndProc(hwnd, message, mp1, mp2)
  512. HWND    hwnd;
  513. USHORT  message;
  514. MPARAM   mp1;
  515. MPARAM   mp2;
  516. {
  517.     switch (message) {
  518.         case WM_COMMAND:
  519.             WinDismissDlg(hwnd, TRUE);
  520.             break;
  521.         default:
  522.             return(WinDefDlgProc(hwnd, message, mp1, mp2));
  523.             break;
  524.     }
  525.     return 0L;
  526.  
  527. } /* end aboutwndproc */
  528.  
  529. void SaveBitmap(void)
  530. {
  531.     HFILE hFile;
  532.     HBITMAP hbm;
  533.     HPOINTER hptr, hptrWait;
  534.  
  535.     WinOpenClipbrd(habSnap);
  536.     if ((hbm = WinQueryClipbrdData(habSnap, CF_BITMAP)) == NULL) {
  537.         WinCloseClipbrd(habSnap);
  538.         return;
  539.     }
  540.  
  541.     if (hFile = OpenSaveFile(hwndSnap)) {
  542.         hptr = WinQueryPointer(HWND_DESKTOP);
  543.         hptrWait = WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, TRUE);
  544.         WinSetPointer(HWND_DESKTOP, hptrWait);
  545.         SaveBitmap2(hFile, hbm);
  546.         WinSetPointer(HWND_DESKTOP, hptr);
  547.         WinDestroyPointer(hptrWait);
  548.     } else
  549.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  550.  
  551.     WinCloseClipbrd(habSnap);
  552. }
  553.  
  554. /***************************************************************************\
  555. * hFile is a handle to an open file.  This is closed on exit.
  556. \***************************************************************************/
  557. void SaveBitmap2(hFile, hbm)
  558. HFILE hFile;
  559. HBITMAP hbm;
  560. {
  561.     /*
  562.      * Currently, this puts stuff out in Win386 paint format.
  563.      */
  564.     typedef struct _WIN386PAINT {
  565.         USHORT key1;
  566.         USHORT key2;
  567.         USHORT dxFile;
  568.         USHORT dyFile;
  569.         USHORT ScrAspectX;
  570.         USHORT ScrAspectY;
  571.         USHORT PrnAspectX;
  572.         USHORT PrnAspectY;
  573.         USHORT dxPrinter;
  574.         USHORT dyPrinter;
  575.         USHORT AspCorX;
  576.         USHORT AspCorY;
  577.         USHORT wCheck;
  578.         USHORT res1;
  579.         USHORT res2;
  580.         USHORT res3;
  581.     } FHDR;
  582.     FHDR hdr;
  583.     int    i;
  584.     USHORT cBytesWritten;
  585.     USHORT *pIndex;
  586.     USHORT *pIndexT;
  587.     NPBYTE pScanLine, pBits, pBitsT;
  588.     USHORT *phdr;
  589.     USHORT cbIndexTable, cbScanLine, cbScanLineExp, cbBmpLine;
  590.     HDC hdc;
  591.     HBITMAP hbmOld;
  592.     BITMAPINFOHEADER bminfo;
  593.     HPS hpsMem;
  594.     SIZEL size;
  595.  
  596.     /*
  597.      * write header
  598.      */
  599.     GpiQueryBitmapParameters(hbm, &bminfo);
  600.     hdr.key1 = 0x694C;
  601.     hdr.key2 = 0x536E;
  602.     hdr.dxFile = bminfo.cx;
  603.     hdr.dyFile = bminfo.cy;
  604.     hdr.ScrAspectX = 26;
  605.     hdr.ScrAspectY = 30;
  606.     hdr.PrnAspectX = 0x12c;
  607.     hdr.PrnAspectY = 0x12c;
  608.     hdr.dxPrinter = 0x8df;
  609.     hdr.dyPrinter = 0xce1;
  610.     hdr.AspCorX = 0;
  611.     hdr.AspCorY = 0;
  612.  
  613.     phdr = (USHORT *)&hdr;
  614.     hdr.wCheck = 0;
  615.     for (i=0; i < 12; i++)
  616.         hdr.wCheck ^= *phdr++;
  617.  
  618.     hdr.res1 = 0;
  619.     hdr.res2 = 0;
  620.     hdr.res3 = 0;
  621.  
  622.     DosWrite(hFile, (PSZ)&hdr, sizeof(FHDR), (PUSHORT)&cBytesWritten);
  623.  
  624.     /* calculate sizes */
  625.     cbIndexTable = sizeof(unsigned int) * bminfo.cy;
  626.     cbScanLine = (bminfo.cx + 7) >> 3;
  627.     cbScanLineExp = cbScanLine + ((cbScanLine + 0xff) >> 8);
  628.     cbBmpLine = (cbScanLine + 3) & 0xfffc;
  629.  
  630.     /*
  631.      * Write index table - (no compression)
  632.      */
  633.     /* allocate pIndex */
  634.     if ((pIndex = (USHORT *)WinAllocMem(hHeap, cbIndexTable)) == NULL) {
  635.         WinFreeMem(hHeap, (NPBYTE)pIndex, cbIndexTable);
  636.         goto Exit;
  637.     }
  638.     pIndexT = pIndex;
  639.     for (i=0; i < bminfo.cy; i++)
  640.         *pIndexT++ = cbScanLineExp;
  641.  
  642.     DosWrite(hFile, (PSZ)pIndex, cbIndexTable, &cBytesWritten);
  643.  
  644.     /* free pIndex */
  645.     WinFreeMem(hHeap, (NPBYTE)pIndex, cbIndexTable);
  646.  
  647.     /*
  648.      * Write out each scan line
  649.      */
  650.     /* allocate pScanLine */
  651.     if ((pScanLine = WinAllocMem(hHeap, cbScanLineExp)) == NULL) {
  652.         WinFreeMem(hHeap, (NPBYTE)pScanLine, cbScanLineExp);
  653.         goto Exit;
  654.     }
  655.     /* allocate pBits */
  656.     if ((pBits = WinAllocMem(hHeap, cbBmpLine * bminfo.cy)) == NULL) {
  657.         WinFreeMem(hHeap, pBits, cbBmpLine * bminfo.cy);
  658.         goto Exit;
  659.     }
  660.  
  661.     /* specify the bitmap format we want */
  662.     bminfo.cPlanes = 1;
  663.     bminfo.cBitCount = 1;
  664.  
  665.     /* Create memory DC */
  666.     hdc = CreateDC((PSZ)"MEMORY", (HDC)NULL);
  667.  
  668.     /* create a memory PS */
  669.     size.cx = bminfo.cx;
  670.     size.cy = bminfo.cy;
  671.     hpsMem = GpiCreatePS( habSnap, hdc, &size,
  672.             PU_ARBITRARY | GPIT_NORMAL | GPIA_ASSOC);
  673.  
  674.     hbmOld = GpiSetBitmap(hpsMem, hbm);
  675.     GpiQueryBitmapBits(hpsMem, (LONG)0, (LONG)bminfo.cy, (PBYTE)pBits,
  676.             (PBITMAPINFO)&bminfo);
  677.  
  678.     pBitsT = pBits + cbBmpLine * bminfo.cy;
  679.     for (i = 0; i < bminfo.cy; i++) {
  680.         pBitsT -= cbBmpLine;
  681.         Copy(pBitsT, pScanLine, cbScanLine);
  682.         convert(pScanLine, cbScanLine, cbScanLineExp);
  683.         DosWrite(hFile, (PSZ)pScanLine, cbScanLineExp, &cBytesWritten);
  684.     }
  685.  
  686.     /* free pBits and pScanLine */
  687.     WinFreeMem(hHeap, pBits, cbScanLine * bminfo.cy);
  688.     WinFreeMem(hHeap, pScanLine, cbScanLineExp);
  689.  
  690.     GpiAssociate(hpsMem, NULL);
  691.     DevCloseDC(hdc);
  692.     GpiDestroyPS(hpsMem);
  693.  
  694. Exit:
  695.     DosClose(hFile);
  696. }
  697.  
  698.  
  699. /***************************************************************************\
  700. * Insert apropriate repeat count bytes into the scanline given.
  701. \***************************************************************************/
  702. void convert(pbuf, cch, cch2)
  703. NPBYTE pbuf;
  704. USHORT cch; /* exact length of buffer BEFORE count bytes have been added */
  705. USHORT cch2; /* AFTER conversion size */
  706. {
  707.     NPBYTE pWrite, pRead;
  708.  
  709.     pWrite = pbuf + cch2 - 1;
  710.     pRead = pbuf + cch - 1;
  711.     while (pWrite > pbuf) {
  712.         *pWrite-- = *pRead--;
  713.         if (((pWrite - pbuf) & 0x00ff) == 0) {
  714.             *pWrite-- = (BYTE)((pbuf + cch2 - pWrite) < 0x100 ?
  715.                     (pbuf + cch2 - pWrite) : 0xff);
  716.         }
  717.     }
  718. }
  719.  
  720. void Copy(src, dest, cb)
  721. NPBYTE src;
  722. NPBYTE dest;
  723. USHORT cb;
  724. {
  725.     USHORT i;
  726.  
  727.     for (i = 0; i < cb; i++)
  728.         *dest++ = *src++;
  729. }
  730.  
  731. HFILE OpenSaveFile(hwnd)
  732. HWND hwnd;
  733. {
  734.     HFILE   hFile= 0L;
  735.     DLGP    dlgp;
  736.     char    fName[32];
  737.     USHORT  action;
  738.  
  739.     dlgp.cch = 32;
  740.     dlgp.psz = fName;
  741.     if (WinDlgBox(HWND_DESKTOP, hwnd, (PFNWP)SaveFileDlgProc, NULL,
  742.             IDD_SAVEFILE, (PVOID)&dlgp) != 0) {
  743.         DosOpen(fName, &hFile, &action, 0L, 0, 0x0011, 0x0011, 0L);
  744.     }
  745.     return(hFile);
  746. }
  747.  
  748. MRESULT CALLBACK SaveFileDlgProc(hwnd, msg, mp1, mp2)
  749. HWND hwnd;
  750. USHORT msg;
  751. MPARAM mp1;
  752. MPARAM mp2;
  753. {
  754.     DLGP FAR *pdlgp;
  755.     SHORT cch;
  756.  
  757.     switch (msg) {
  758.     case WM_INITDLG:
  759.         /* squirl away the dlgp pointer in a reentrant fashion */
  760.         WinSetWindowULong(hwnd, QWL_USER, (ULONG)mp2);
  761.         break;
  762.  
  763.     case WM_CHAR:
  764.         if ( ((USHORT)mp1 & KC_VIRTUALKEY) &&
  765.                 ((SHORT2FROMMP(mp2) == VK_NEWLINE) ||
  766.                  (SHORT2FROMMP(mp2) == VK_ENTER)) ) {
  767.             if (pdlgp = (DLGP FAR *)WinQueryWindowULong(hwnd, QWL_USER)) {
  768.                 cch = WinQueryWindowText(WinWindowFromID(hwnd, ID_FILEENTRY),
  769.                         pdlgp->cch, pdlgp->psz);
  770.                 WinDismissDlg(hwnd, cch);
  771.             } else {
  772.                 WinDismissDlg(hwnd, 0);
  773.             }
  774.             return(0);
  775.         }
  776.         break;
  777.     }
  778.  
  779.     return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  780. }
  781.